package com.jimmy.medical.wechat;

import com.alibaba.fastjson.JSONObject;
import com.jimmy.medical.wechat.model.AccessTokenEntity;
import com.jimmy.medical.wechat.model.JsTicketEntity;
import com.jimmy.medical.wechat.model.UserInfoAccessEntity;
import com.jimmy.medical.wechat.model.UserInfoEntity;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.ConnectException;
import java.net.HttpURLConnection;
import java.net.URL;

@Slf4j
@Component
public class WeChatHttp {

	private static final String TAG = WeChatHttp.class.getName();

	@Autowired
	WeChatPayConfig weChatPayConfig;

	@Autowired
	WeChatUrlHelper weChatUrlHelper;

	public JSONObject httpGet(String requestUrl) {
		String rst = httpRequest(requestUrl, "GET");
		if (rst == null || rst.isEmpty()) {
			return null;
		}
		return JSONObject.parseObject(rst);
	}

	public <T> T httpGet(String requestUrl, Class<T> classType) {
		String rst = httpRequest(requestUrl, "GET");
		if (rst == null || rst.isEmpty()) {
			return null;
		}
		return JSONObject.parseObject(rst, classType);
	}

	public JSONObject httpPost(String requestUrl) {
		String rst = httpRequest(requestUrl, "POST");
		if (rst == null || rst.isEmpty()) {
			return null;
		}
		return JSONObject.parseObject(rst);
	}

	public <T> T httpPost(String requestUrl, Class<T> classType) {
		String rst = httpRequest(requestUrl, "POST");
		if (rst == null || rst.isEmpty()) {
			return null;
		}
		return JSONObject.parseObject(rst, classType);
	}

	public String httpRequest(String requestUrl, String requestMethod) {
		String rstStr = null;
		StringBuffer buffer = new StringBuffer();
		try {
			// 创建url资源
			URL url = new URL(requestUrl);
			log.info(TAG, "连接微信API服务器(" + requestMethod + "):" + requestUrl);
			// http协议传输:建立http连接
			HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
			// 设置允许输出
			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			// 设置不用缓存
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);
			// 设置维持长连接
			httpUrlConn.setRequestProperty("Connection", "Keep-Alive");
			// 设置文件字符集:
			httpUrlConn.setRequestProperty("Charset", "UTF-8");

			// // 设置文件长度
			// httpUrlConn.setRequestProperty("Content-Length",
			// String.valueOf(data.length));
			// // 设置文件类型:
			// httpUrlConn.setRequestProperty("contentType",
			// "application/json");

			// 开始连接请求
			if ("GET".equalsIgnoreCase(requestMethod)) {
				httpUrlConn.connect();
			}
			// 请求返回的状态
			if (httpUrlConn.getResponseCode() == 200) {
				log.info(TAG, "连接微信API服务器成功");
				// 将返回的输入流转换成字符串
				InputStream inputStream = httpUrlConn.getInputStream();
				InputStreamReader inputStreamReader = new InputStreamReader(
						inputStream, "utf-8");
				BufferedReader bufferedReader = new BufferedReader(
						inputStreamReader);

				String str = null;
				while ((str = bufferedReader.readLine()) != null) {
					buffer.append(str);
				}
				// 释放资源
				bufferedReader.close();
				inputStreamReader.close();
				inputStream.close();
				inputStream = null;
				httpUrlConn.disconnect();
				rstStr = buffer.toString();
				log.info(TAG, "连接微信API服务器返回：" + rstStr);
			} else {
				log.info(TAG, "连接微信API服务器失败：(" + httpUrlConn.getResponseCode()+ ")" + httpUrlConn.getResponseMessage());
			}
		} catch (Exception e) {
			e.printStackTrace();
			log.info(TAG, "连接微信API服务器失败：" + e.getMessage());
		}
		return rstStr;
	}

	/**
	 * 请求微信API端，并传入string
	 * */
	public String httpsRequest(String requestUrl, String requestMethod,String outputStr) {
		String rstStr = null;
		try {
			URL url = new URL(requestUrl);
			log.info(TAG, "连接微信API服务器(" + requestMethod + "):" + requestUrl);
			HttpURLConnection httpUrlConn = (HttpURLConnection) url.openConnection();
			// 设置允许输出
			httpUrlConn.setDoOutput(true);
			httpUrlConn.setDoInput(true);
			// 设置不用缓存
			httpUrlConn.setUseCaches(false);
			// 设置请求方式（GET/POST）
			httpUrlConn.setRequestMethod(requestMethod);
			// 设置文件字符集:
			httpUrlConn.setRequestProperty("content-type","application/x-www-form-urlencoded");
			// 当outputStr不为null时向输出流写数据
			if (null != outputStr) {
				log.info(TAG, "提交数据:"+outputStr);
				OutputStream outputStream = httpUrlConn.getOutputStream();
				// 传入String参数到服务器(注意编码格式)
				outputStream.write(outputStr.getBytes("UTF-8"));
				// 关闭传输通道
				outputStream.close();
			}
			// 请求返回的状态
			if (httpUrlConn.getResponseCode() == 200) {
				log.info(TAG, "连接微信API服务器成功");
				// 从输入流读取返回内容
				InputStream inputStream = httpUrlConn.getInputStream();
				InputStreamReader inputStreamReader = new InputStreamReader(
						inputStream, "utf-8");
				BufferedReader bufferedReader = new BufferedReader(
						inputStreamReader);
				String str = null;
				StringBuffer buffer = new StringBuffer();
				while ((str = bufferedReader.readLine()) != null) {
					buffer.append(str);
				}
				// 释放资源
				bufferedReader.close();
				inputStreamReader.close();
				inputStream.close();
				inputStream = null;
				httpUrlConn.disconnect();
				rstStr = buffer.toString();
				log.info(TAG, "连接微信API服务器返回：" + rstStr);
			} else {
				log.info(TAG, "连接微信API服务器失败：(" + httpUrlConn.getResponseCode()+ ")" + httpUrlConn.getResponseMessage());
			}
		} catch (ConnectException ce) {
			log.info(TAG, "连接超时：{}" + ce);
		} catch (Exception e) {
			log.info(TAG, "https请求异常：{}" + e);
		}
		return rstStr;
	}

	/**
	 * 刷新微信API ACCESS-TOKEN
	 * success:{"access_token":"ACCESS_TOKEN","expires_in":7200}
	 * failed:{"errcode":40013,"errmsg":"invalid appid"}
	 * */
	public JSONObject getAPIAccessTokenJson() {
		return httpGet(weChatPayConfig.API_URL_ACCESSTOKEN);
	}

	/**
	 * 刷新微信API ACCESS-TOKEN
	 * success:{"access_token":"ACCESS_TOKEN","expires_in":7200}
	 * failed:{"errcode":40013,"errmsg":"invalid appid"}
	 * */
	public AccessTokenEntity getAPIAccessToken() {
		return httpGet(weChatPayConfig.API_URL_ACCESSTOKEN,
				AccessTokenEntity.class);
	}

	/**
	 * 刷新微信API JS-TICKET {"errcode":0,"errmsg":"ok","ticket":"bxLdikRXVbTPdHSM05e5u5sUoXNKd8-41ZO3MhKoyN5OfkWITDGgnr2fwJ0m9E8NYzWKVZvdVtaUgWvsdshFKA"
	 * ,"expires_in":7200}
	 * */
	public JsTicketEntity getAPIJSTicket(String accessToken) {
		return httpGet(weChatUrlHelper.getJSTicketUrl(accessToken),
				JsTicketEntity.class);
	}

	/**
	 * 获取用户信息授权 成功结果：{ "access_token":"ACCESS_TOKEN", "expires_in":7200,
	 * "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
	 * 失败结果：{"errcode":40029,"errmsg":"invalid code"}
	 * */
	public JSONObject getUserInfoAccessJson(String code) {
		String requestUrl = weChatUrlHelper.getUserAccessTokenUrl(code);
		if (requestUrl == null) {
			log.info(TAG, "getUserInfoAccess失败：null code!");
			return null;
		}
		JSONObject rst = httpGet(requestUrl);
		log.info(TAG, "getUserInfoAccess 成功:" + rst);
		return rst;
	}

	/**
	 * 获取用户信息授权 成功结果：{ "access_token":"ACCESS_TOKEN", "expires_in":7200,
	 * "refresh_token":"REFRESH_TOKEN", "openid":"OPENID", "scope":"SCOPE" }
	 * 失败结果：{"errcode":40029,"errmsg":"invalid code"}
	 * */
	public UserInfoAccessEntity getUserInfoAccess(String code) {
		String requestUrl = weChatUrlHelper.getUserAccessTokenUrl(code);
		if (requestUrl == null) {
			log.info(TAG, "getUserInfoAccess失败：null code!");
			return null;
		}
		UserInfoAccessEntity rst = httpGet(requestUrl,
				UserInfoAccessEntity.class);
		rst.setCreateTime(System.currentTimeMillis());
		if (rst == null || StringUtils.isEmpty(rst.getAccessToken())) {
			log.info(TAG, "getUserInfoAccess 失败");
		} else {
			log.info(TAG, "getUserInfoAccess 成功:" + rst.getAccessToken());
		}
		return rst;
	}

	/**
	 * 获取用户信息 成功JSON:{ "openid":" OPENID", " nickname": NICKNAME, "sex":"1",
	 * "province":"PROVINCE" "city":"CITY", "country":"COUNTRY",
	 * "headimgurl":"http://wx.qlogo.cn/mmopen/xxxxxxx", "privilege":[
	 * "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
	 * 失败JSON：{"errcode":40003,"errmsg":" invalid openid "}
	 * */
	public JSONObject getUserInfoJson(String accessToken, String openId) {
		String requestUrl = weChatUrlHelper.getUserInfoUrl(accessToken, openId);
		if (requestUrl == null) {
			log.info(TAG, "getUserInfo失败：null accessToken or openId!");
			return null;
		}
		JSONObject rst = httpGet(requestUrl);
		log.info(TAG, "getUserInfo 成功:" + rst);
		return rst;
	}

	/**
	 * 获取用户信息 成功JSON:{ "openid":" OPENID", " nickname": NICKNAME, "sex":"1",
	 * "province":"PROVINCE" "city":"CITY", "country":"COUNTRY",
	 * "headimgurl":"http://wx.qlogo.cn/mmopen/xxxxxxx", "privilege":[
	 * "PRIVILEGE1" "PRIVILEGE2" ], "unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL" }
	 * 失败JSON：{"errcode":40003,"errmsg":" invalid openid "}
	 * */
	public UserInfoEntity getUserInfo(String accessToken, String openId) {
		String requestUrl = weChatUrlHelper.getUserInfoUrl(accessToken, openId);
		if (requestUrl == null) {
			log.info(TAG, "getUserInfo失败：null accessToken or openId!");
			return null;
		}
		UserInfoEntity rst = httpGet(requestUrl, UserInfoEntity.class);
		log.info(TAG, "getUserInfo 成功:" + rst);
		return rst;
	}
}
